<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: More Morphology Transformations</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d9/df8/tutorial_root.html">OpenCV Tutorials</a></li><li class="navelem"><a class="el" href="../../d7/da8/tutorial_table_of_content_imgproc.html">Image Processing (imgproc module)</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">More Morphology Transformations </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p><b>Prev Tutorial:</b> <a class="el" href="../../db/df6/tutorial_erosion_dilatation.html">Eroding and Dilating</a></p>
<p><b>Next Tutorial:</b> <a class="el" href="../../db/d06/tutorial_hitOrMiss.html">Hit-or-Miss</a></p>
<table class="doxtable">
<tr>
<th align="right"></th><th align="left"></th></tr>
<tr>
<td align="right">Original author </td><td align="left">Ana Huamán </td></tr>
<tr>
<td align="right">Compatibility </td><td align="left">OpenCV &gt;= 3.0 </td></tr>
</table>
<h2>Goal </h2>
<p>In this tutorial you will learn how to:</p>
<ul>
<li>Use the OpenCV function <a class="el" href="../../d4/d86/group__imgproc__filter.html#ga67493776e3ad1a3df63883829375201f">cv::morphologyEx</a> to apply Morphological Transformation such as:<ul>
<li>Opening</li>
<li>Closing</li>
<li>Morphological Gradient</li>
<li>Top Hat</li>
<li>Black Hat</li>
</ul>
</li>
</ul>
<h2>Theory </h2>
<dl class="section note"><dt>Note</dt><dd>The explanation below belongs to the book <b>Learning OpenCV</b> by Bradski and Kaehler.</dd></dl>
<p>In the previous tutorial we covered two basic Morphology operations:</p>
<ul>
<li>Erosion</li>
<li>Dilation.</li>
</ul>
<p>Based on these two we can effectuate more sophisticated transformations to our images. Here we discuss briefly 5 operations offered by OpenCV:</p>
<h3>Opening</h3>
<ul>
<li><p class="startli">It is obtained by the erosion of an image followed by a dilation.</p>
<p class="formulaDsp">
\[dst = open( src, element) = dilate( erode( src, element ) )\]
</p>
</li>
<li>Useful for removing small objects (it is assumed that the objects are bright on a dark foreground)</li>
<li><p class="startli">For instance, check out the example below. The image at the left is the original and the image at the right is the result after applying the opening transformation. We can observe that the small dots have disappeared.</p>
<div class="image">
<img src="../../Morphology_2_Tutorial_Theory_Opening.png" alt="Morphology_2_Tutorial_Theory_Opening.png"/>
</div>
</li>
</ul>
<h3>Closing</h3>
<ul>
<li><p class="startli">It is obtained by the dilation of an image followed by an erosion.</p>
<p class="formulaDsp">
\[dst = close( src, element ) = erode( dilate( src, element ) )\]
</p>
</li>
<li><p class="startli">Useful to remove small holes (dark regions).</p>
<div class="image">
<img src="../../Morphology_2_Tutorial_Theory_Closing.png" alt="Morphology_2_Tutorial_Theory_Closing.png"/>
</div>
</li>
</ul>
<h3>Morphological Gradient</h3>
<ul>
<li><p class="startli">It is the difference between the dilation and the erosion of an image.</p>
<p class="formulaDsp">
\[dst = morph_{grad}( src, element ) = dilate( src, element ) - erode( src, element )\]
</p>
</li>
<li><p class="startli">It is useful for finding the outline of an object as can be seen below:</p>
<div class="image">
<img src="../../Morphology_2_Tutorial_Theory_Gradient.png" alt="Morphology_2_Tutorial_Theory_Gradient.png"/>
</div>
</li>
</ul>
<h3>Top Hat</h3>
<ul>
<li><p class="startli">It is the difference between an input image and its opening.</p>
<p class="formulaDsp">
\[dst = tophat( src, element ) = src - open( src, element )\]
</p>
<div class="image">
<img src="../../Morphology_2_Tutorial_Theory_TopHat.png" alt="Morphology_2_Tutorial_Theory_TopHat.png"/>
</div>
</li>
</ul>
<h3>Black Hat</h3>
<ul>
<li><p class="startli">It is the difference between the closing and its input image</p>
<p class="formulaDsp">
\[dst = blackhat( src, element ) = close( src, element ) - src\]
</p>
<div class="image">
<img src="../../Morphology_2_Tutorial_Theory_BlackHat.png" alt="Morphology_2_Tutorial_Theory_BlackHat.png"/>
</div>
</li>
</ul>
<h2>Code </h2>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'><p> This tutorial's code is shown below. You can also download it <a href="https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Morphology_2.cpp">here</a> </p><div class="fragment"><div class="line"></div><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="../../d1/d4f/imgproc_2include_2opencv2_2imgproc_8hpp.html">opencv2/imgproc.hpp</a>&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="../../d6/d87/imgcodecs_8hpp.html">opencv2/imgcodecs.hpp</a>&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="../../d4/dd5/highgui_8hpp.html">opencv2/highgui.hpp</a>&quot;</span></div><div class="line"><span class="preprocessor">#include &lt;iostream&gt;</span></div><div class="line"></div><div class="line"><span class="keyword">using namespace </span><a class="code" href="../../d2/d75/namespacecv.html">cv</a>;</div><div class="line"></div><div class="line"><a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> src, dst;</div><div class="line"></div><div class="line"><span class="keywordtype">int</span> morph_elem = 0;</div><div class="line"><span class="keywordtype">int</span> morph_size = 0;</div><div class="line"><span class="keywordtype">int</span> morph_operator = 0;</div><div class="line"><span class="keywordtype">int</span> <span class="keyword">const</span> max_operator = 4;</div><div class="line"><span class="keywordtype">int</span> <span class="keyword">const</span> max_elem = 2;</div><div class="line"><span class="keywordtype">int</span> <span class="keyword">const</span> max_kernel_size = 21;</div><div class="line"></div><div class="line"><span class="keyword">const</span> <span class="keywordtype">char</span>* window_name = <span class="stringliteral">&quot;Morphology Transformations Demo&quot;</span>;</div><div class="line"></div><div class="line"></div><div class="line"><span class="keywordtype">void</span> Morphology_Operations( <span class="keywordtype">int</span>, <span class="keywordtype">void</span>* );</div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main( <span class="keywordtype">int</span> argc, <span class="keywordtype">char</span>** argv )</div><div class="line">{</div><div class="line">  <a class="code" href="../../d0/d2e/classcv_1_1CommandLineParser.html">CommandLineParser</a> parser( argc, argv, <span class="stringliteral">&quot;{@input | baboon.jpg | input image}&quot;</span> );</div><div class="line">  src = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">imread</a>( <a class="code" href="../../d6/dba/group__core__utils__samples.html#ga3a33b00033b46c698ff6340d95569c13">samples::findFile</a>( parser.get&lt;<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>&gt;( <span class="stringliteral">&quot;@input&quot;</span> ) ), <a class="code" href="../../d8/d6a/group__imgcodecs__flags.html#gga61d9b0126a3e57d9277ac48327799c80af660544735200cbe942eea09232eb822">IMREAD_COLOR</a> );</div><div class="line">  <span class="keywordflow">if</span> (src.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#abbec3525a852e77998aba034813fded4">empty</a>())</div><div class="line">  {</div><div class="line">    std::cout &lt;&lt; <span class="stringliteral">&quot;Could not open or find the image!\n&quot;</span> &lt;&lt; std::endl;</div><div class="line">    std::cout &lt;&lt; <span class="stringliteral">&quot;Usage: &quot;</span> &lt;&lt; argv[0] &lt;&lt; <span class="stringliteral">&quot; &lt;Input image&gt;&quot;</span> &lt;&lt; std::endl;</div><div class="line">    <span class="keywordflow">return</span> EXIT_FAILURE;</div><div class="line">  }</div><div class="line"></div><div class="line">  <a class="code" href="../../d7/dfc/group__highgui.html#ga5afdf8410934fd099df85c75b2e0888b">namedWindow</a>( window_name, <a class="code" href="../../d0/d90/group__highgui__window__flags.html#ggabf7d2c5625bc59ac130287f925557ac3acf621ace7a54954cbac01df27e47228f">WINDOW_AUTOSIZE</a> ); <span class="comment">// Create window</span></div><div class="line"><span class="comment"></span></div><div class="line">  <a class="code" href="../../d7/dfc/group__highgui.html#gaf78d2155d30b728fc413803745b67a9b">createTrackbar</a>(<span class="stringliteral">&quot;Operator:\n 0: Opening - 1: Closing  \n 2: Gradient - 3: Top Hat \n 4: Black Hat&quot;</span>, window_name, &amp;morph_operator, max_operator, Morphology_Operations );</div><div class="line"></div><div class="line">  <a class="code" href="../../d7/dfc/group__highgui.html#gaf78d2155d30b728fc413803745b67a9b">createTrackbar</a>( <span class="stringliteral">&quot;Element:\n 0: Rect - 1: Cross - 2: Ellipse&quot;</span>, window_name,</div><div class="line">                  &amp;morph_elem, max_elem,</div><div class="line">                  Morphology_Operations );</div><div class="line"></div><div class="line">  <a class="code" href="../../d7/dfc/group__highgui.html#gaf78d2155d30b728fc413803745b67a9b">createTrackbar</a>( <span class="stringliteral">&quot;Kernel size:\n 2n +1&quot;</span>, window_name,</div><div class="line">                  &amp;morph_size, max_kernel_size,</div><div class="line">                  Morphology_Operations );</div><div class="line"></div><div class="line">  Morphology_Operations( 0, 0 );</div><div class="line"></div><div class="line">  <a class="code" href="../../d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7">waitKey</a>(0);</div><div class="line">  <span class="keywordflow">return</span> 0;</div><div class="line">}</div><div class="line"></div><div class="line"></div><div class="line"><span class="keywordtype">void</span> Morphology_Operations( <span class="keywordtype">int</span>, <span class="keywordtype">void</span>* )</div><div class="line">{</div><div class="line">  <span class="comment">// Since MORPH_X : 2,3,4,5 and 6</span></div><div class="line"><span class="comment"></span>  <span class="keywordtype">int</span> operation = morph_operator + 2;</div><div class="line"></div><div class="line">  <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> element = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gac342a1bb6eabf6f55c803b09268e36dc">getStructuringElement</a>( morph_elem, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>( 2*morph_size + 1, 2*morph_size+1 ), <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>( morph_size, morph_size ) );</div><div class="line"></div><div class="line">  <a class="code" href="../../d4/d86/group__imgproc__filter.html#ga67493776e3ad1a3df63883829375201f">morphologyEx</a>( src, dst, operation, element );</div><div class="line">  <a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">imshow</a>( window_name, dst );</div><div class="line">}</div></div><!-- fragment -->  </div>  <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'><p> This tutorial's code is shown below. You can also download it <a href="https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/ImgProc/opening_closing_hats/MorphologyDemo2.java">here</a> </p><div class="fragment"><div class="line"><span class="keyword">import</span> java.awt.BorderLayout;</div><div class="line"><span class="keyword">import</span> java.awt.Container;</div><div class="line"><span class="keyword">import</span> java.awt.Image;</div><div class="line"><span class="keyword">import</span> java.awt.event.ActionEvent;</div><div class="line"><span class="keyword">import</span> java.awt.event.ActionListener;</div><div class="line"></div><div class="line"><span class="keyword">import</span> javax.swing.BoxLayout;</div><div class="line"><span class="keyword">import</span> javax.swing.ImageIcon;</div><div class="line"><span class="keyword">import</span> javax.swing.JComboBox;</div><div class="line"><span class="keyword">import</span> javax.swing.JFrame;</div><div class="line"><span class="keyword">import</span> javax.swing.JLabel;</div><div class="line"><span class="keyword">import</span> javax.swing.JPanel;</div><div class="line"><span class="keyword">import</span> javax.swing.JSlider;</div><div class="line"><span class="keyword">import</span> javax.swing.event.ChangeEvent;</div><div class="line"><span class="keyword">import</span> javax.swing.event.ChangeListener;</div><div class="line"></div><div class="line"><span class="keyword">import</span> org.opencv.core.Core;</div><div class="line"><span class="keyword">import</span> org.opencv.core.Mat;</div><div class="line"><span class="keyword">import</span> org.opencv.core.Point;</div><div class="line"><span class="keyword">import</span> org.opencv.core.Size;</div><div class="line"><span class="keyword">import</span> org.opencv.highgui.HighGui;</div><div class="line"><span class="keyword">import</span> org.opencv.imgcodecs.Imgcodecs;</div><div class="line"><span class="keyword">import</span> org.opencv.imgproc.Imgproc;</div><div class="line"></div><div class="line"><span class="keyword">public</span> <span class="keyword">class </span>MorphologyDemo2 {</div><div class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>[] MORPH_OP = { <span class="stringliteral">&quot;Opening&quot;</span>, <span class="stringliteral">&quot;Closing&quot;</span>, <span class="stringliteral">&quot;Gradient&quot;</span>, <span class="stringliteral">&quot;Top Hat&quot;</span>, <span class="stringliteral">&quot;Black Hat&quot;</span> };</div><div class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keywordtype">int</span>[] MORPH_OP_TYPE = { Imgproc.MORPH_OPEN, Imgproc.MORPH_CLOSE,</div><div class="line">            Imgproc.MORPH_GRADIENT, Imgproc.MORPH_TOPHAT, Imgproc.MORPH_BLACKHAT };</div><div class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>[] ELEMENT_TYPE = { <span class="stringliteral">&quot;Rectangle&quot;</span>, <span class="stringliteral">&quot;Cross&quot;</span>, <span class="stringliteral">&quot;Ellipse&quot;</span> };</div><div class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keywordtype">int</span> MAX_KERNEL_SIZE = 21;</div><div class="line">    <span class="keyword">private</span> Mat matImgSrc;</div><div class="line">    <span class="keyword">private</span> Mat matImgDst = <span class="keyword">new</span> Mat();</div><div class="line">    <span class="keyword">private</span> <span class="keywordtype">int</span> morphOpType = Imgproc.MORPH_OPEN;</div><div class="line">    <span class="keyword">private</span> <span class="keywordtype">int</span> elementType = Imgproc.CV_SHAPE_RECT;</div><div class="line">    <span class="keyword">private</span> <span class="keywordtype">int</span> kernelSize = 0;</div><div class="line">    <span class="keyword">private</span> JFrame frame;</div><div class="line">    <span class="keyword">private</span> JLabel imgLabel;</div><div class="line"></div><div class="line">    <span class="keyword">public</span> MorphologyDemo2(<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>[] args) {</div><div class="line">        <a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a> imagePath = args.length &gt; 0 ? args[0] : <span class="stringliteral">&quot;../data/LinuxLogo.jpg&quot;</span>;</div><div class="line">        matImgSrc = Imgcodecs.imread(imagePath);</div><div class="line">        <span class="keywordflow">if</span> (matImgSrc.empty()) {</div><div class="line">            System.out.println(<span class="stringliteral">&quot;Empty image: &quot;</span> + imagePath);</div><div class="line">            System.exit(0);</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="comment">// Create and set up the window.</span></div><div class="line">        frame = <span class="keyword">new</span> JFrame(<span class="stringliteral">&quot;Morphology Transformations demo&quot;</span>);</div><div class="line">        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);</div><div class="line">        <span class="comment">// Set up the content pane.</span></div><div class="line">        Image img = HighGui.toBufferedImage(matImgSrc);</div><div class="line">        addComponentsToPane(frame.getContentPane(), img);</div><div class="line">        <span class="comment">// Use the content pane&#39;s default BorderLayout. No need for</span></div><div class="line">        <span class="comment">// setLayout(new BorderLayout());</span></div><div class="line">        <span class="comment">// Display the window.</span></div><div class="line">        frame.pack();</div><div class="line">        frame.setVisible(<span class="keyword">true</span>);</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="keyword">private</span> <span class="keywordtype">void</span> addComponentsToPane(Container pane, Image img) {</div><div class="line">        <span class="keywordflow">if</span> (!(pane.getLayout() instanceof BorderLayout)) {</div><div class="line">            pane.add(<span class="keyword">new</span> JLabel(<span class="stringliteral">&quot;Container doesn&#39;t use BorderLayout!&quot;</span>));</div><div class="line">            <span class="keywordflow">return</span>;</div><div class="line">        }</div><div class="line"></div><div class="line">        JPanel sliderPanel = <span class="keyword">new</span> JPanel();</div><div class="line">        sliderPanel.setLayout(<span class="keyword">new</span> BoxLayout(sliderPanel, BoxLayout.PAGE_AXIS));</div><div class="line"></div><div class="line">        JComboBox&lt;String&gt; morphOpBox = <span class="keyword">new</span> JComboBox&lt;&gt;(MORPH_OP);</div><div class="line">        morphOpBox.addActionListener(<span class="keyword">new</span> ActionListener() {</div><div class="line">            @Override</div><div class="line">            <span class="keyword">public</span> <span class="keywordtype">void</span> actionPerformed(ActionEvent e) {</div><div class="line">                @SuppressWarnings(<span class="stringliteral">&quot;unchecked&quot;</span>)</div><div class="line">                JComboBox&lt;<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>&gt; cb = (JComboBox&lt;<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>&gt;)e.getSource();</div><div class="line">                morphOpType = MORPH_OP_TYPE[cb.getSelectedIndex()];</div><div class="line">                update();</div><div class="line">            }</div><div class="line">        });</div><div class="line">        sliderPanel.<a class="code" href="../../d2/de8/group__core__array.html#ga10ac1bfb180e2cfda1701d06c24fdbd6">add</a>(morphOpBox);</div><div class="line"></div><div class="line">        JComboBox&lt;<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>&gt; elementTypeBox = new JComboBox&lt;&gt;(ELEMENT_TYPE);</div><div class="line">        elementTypeBox.addActionListener(new ActionListener() {</div><div class="line">            @Override</div><div class="line">            <span class="keyword">public</span> <span class="keywordtype">void</span> actionPerformed(ActionEvent e) {</div><div class="line">                @SuppressWarnings(<span class="stringliteral">&quot;unchecked&quot;</span>)</div><div class="line">                JComboBox&lt;<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>&gt; cb = (JComboBox&lt;<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>&gt;)e.getSource();</div><div class="line">                if (cb.getSelectedIndex() == 0) {</div><div class="line">                    elementType = Imgproc.CV_SHAPE_RECT;</div><div class="line">                } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (cb.getSelectedIndex() == 1) {</div><div class="line">                    elementType = Imgproc.CV_SHAPE_CROSS;</div><div class="line">                } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (cb.getSelectedIndex() == 2) {</div><div class="line">                    elementType = Imgproc.CV_SHAPE_ELLIPSE;</div><div class="line">                }</div><div class="line">                update();</div><div class="line">            }</div><div class="line">        });</div><div class="line">        sliderPanel.add(elementTypeBox);</div><div class="line"></div><div class="line">        sliderPanel.add(<span class="keyword">new</span> JLabel(<span class="stringliteral">&quot;Kernel size: 2n + 1&quot;</span>));</div><div class="line">        JSlider slider = <span class="keyword">new</span> JSlider(0, MAX_KERNEL_SIZE, 0);</div><div class="line">        slider.setMajorTickSpacing(5);</div><div class="line">        slider.setMinorTickSpacing(5);</div><div class="line">        slider.setPaintTicks(<span class="keyword">true</span>);</div><div class="line">        slider.setPaintLabels(<span class="keyword">true</span>);</div><div class="line">        slider.addChangeListener(<span class="keyword">new</span> ChangeListener() {</div><div class="line">            @Override</div><div class="line">            <span class="keyword">public</span> <span class="keywordtype">void</span> stateChanged(ChangeEvent e) {</div><div class="line">                JSlider source = (JSlider) e.getSource();</div><div class="line">                kernelSize = source.getValue();</div><div class="line">                update();</div><div class="line">            }</div><div class="line">        });</div><div class="line">        sliderPanel.add(slider);</div><div class="line"></div><div class="line">        pane.add(sliderPanel, BorderLayout.PAGE_START);</div><div class="line">        imgLabel = <span class="keyword">new</span> JLabel(<span class="keyword">new</span> ImageIcon(img));</div><div class="line">        pane.add(imgLabel, BorderLayout.CENTER);</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="keyword">private</span> <span class="keywordtype">void</span> update() {</div><div class="line">        Mat element = Imgproc.getStructuringElement(elementType, <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(2 * kernelSize + 1, 2 * kernelSize + 1),</div><div class="line">                <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(kernelSize, kernelSize));</div><div class="line"></div><div class="line">        Imgproc.morphologyEx(matImgSrc, matImgDst, morphOpType, element);</div><div class="line">        Image img = HighGui.toBufferedImage(matImgDst);</div><div class="line">        imgLabel.setIcon(<span class="keyword">new</span> ImageIcon(img));</div><div class="line">        frame.repaint();</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keywordtype">void</span> main(<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>[] args) {</div><div class="line">        <span class="comment">// Load the native OpenCV library</span></div><div class="line">        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);</div><div class="line"></div><div class="line">        <span class="comment">// Schedule a job for the event dispatch thread:</span></div><div class="line">        <span class="comment">// creating and showing this application&#39;s GUI.</span></div><div class="line">        javax.swing.SwingUtilities.invokeLater(<span class="keyword">new</span> Runnable() {</div><div class="line">            @Override</div><div class="line">            <span class="keyword">public</span> <span class="keywordtype">void</span> run() {</div><div class="line">                <span class="keyword">new</span> MorphologyDemo2(args);</div><div class="line">            }</div><div class="line">        });</div><div class="line">    }</div><div class="line">}</div></div><!-- fragment -->  </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'><p> This tutorial's code is shown below. You can also download it <a href="https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/imgProc/opening_closing_hats/morphology_2.py">here</a> </p><div class="fragment"><div class="line"><span class="keyword">from</span> __future__ <span class="keyword">import</span> print_function</div><div class="line"><span class="keyword">import</span> cv2 <span class="keyword">as</span> cv</div><div class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</div><div class="line"><span class="keyword">import</span> argparse</div><div class="line"></div><div class="line">morph_size = 0</div><div class="line">max_operator = 4</div><div class="line">max_elem = 2</div><div class="line">max_kernel_size = 21</div><div class="line">title_trackbar_operator_type = <span class="stringliteral">&#39;Operator:\n 0: Opening - 1: Closing  \n 2: Gradient - 3: Top Hat \n 4: Black Hat&#39;</span></div><div class="line">title_trackbar_element_type = <span class="stringliteral">&#39;Element:\n 0: Rect - 1: Cross - 2: Ellipse&#39;</span></div><div class="line">title_trackbar_kernel_size = <span class="stringliteral">&#39;Kernel size:\n 2n + 1&#39;</span></div><div class="line">title_window = <span class="stringliteral">&#39;Morphology Transformations Demo&#39;</span></div><div class="line">morph_op_dic = {0: cv.MORPH_OPEN, 1: cv.MORPH_CLOSE, 2: cv.MORPH_GRADIENT, 3: cv.MORPH_TOPHAT, 4: cv.MORPH_BLACKHAT}</div><div class="line"></div><div class="line"><span class="keyword">def </span>morphology_operations(val):</div><div class="line">    morph_operator = <a class="code" href="../../d7/dfc/group__highgui.html#ga122632e9e91b9ec06943472c55d9cda8">cv.getTrackbarPos</a>(title_trackbar_operator_type, title_window)</div><div class="line">    morph_size = <a class="code" href="../../d7/dfc/group__highgui.html#ga122632e9e91b9ec06943472c55d9cda8">cv.getTrackbarPos</a>(title_trackbar_kernel_size, title_window)</div><div class="line">    morph_elem = 0</div><div class="line">    val_type = <a class="code" href="../../d7/dfc/group__highgui.html#ga122632e9e91b9ec06943472c55d9cda8">cv.getTrackbarPos</a>(title_trackbar_element_type, title_window)</div><div class="line">    <span class="keywordflow">if</span> val_type == 0:</div><div class="line">        morph_elem = cv.MORPH_RECT</div><div class="line">    <span class="keywordflow">elif</span> val_type == 1:</div><div class="line">        morph_elem = cv.MORPH_CROSS</div><div class="line">    <span class="keywordflow">elif</span> val_type == 2:</div><div class="line">        morph_elem = cv.MORPH_ELLIPSE</div><div class="line"></div><div class="line">    element = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gac342a1bb6eabf6f55c803b09268e36dc">cv.getStructuringElement</a>(morph_elem, (2*morph_size + 1, 2*morph_size+1), (morph_size, morph_size))</div><div class="line">    operation = morph_op_dic[morph_operator]</div><div class="line">    dst = <a class="code" href="../../d4/d86/group__imgproc__filter.html#ga67493776e3ad1a3df63883829375201f">cv.morphologyEx</a>(src, operation, element)</div><div class="line">    <a class="code" href="../../df/d24/group__highgui__opengl.html#gaae7e90aa3415c68dba22a5ff2cefc25d">cv.imshow</a>(title_window, dst)</div><div class="line"></div><div class="line">parser = argparse.ArgumentParser(description=<span class="stringliteral">&#39;Code for More Morphology Transformations tutorial.&#39;</span>)</div><div class="line">parser.add_argument(<span class="stringliteral">&#39;--input&#39;</span>, help=<span class="stringliteral">&#39;Path to input image.&#39;</span>, default=<span class="stringliteral">&#39;LinuxLogo.jpg&#39;</span>)</div><div class="line">args = parser.parse_args()</div><div class="line"></div><div class="line">src = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">cv.imread</a>(<a class="code" href="../../d6/dba/group__core__utils__samples.html#ga3a33b00033b46c698ff6340d95569c13">cv.samples.findFile</a>(args.input))</div><div class="line"><span class="keywordflow">if</span> src <span class="keywordflow">is</span> <span class="keywordtype">None</span>:</div><div class="line">    <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#a701210a0203f2786cbfd04b2bd56da47">print</a>(<span class="stringliteral">&#39;Could not open or find the image: &#39;</span>, args.input)</div><div class="line">    exit(0)</div><div class="line"></div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#ga5afdf8410934fd099df85c75b2e0888b">cv.namedWindow</a>(title_window)</div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#gaf78d2155d30b728fc413803745b67a9b">cv.createTrackbar</a>(title_trackbar_operator_type, title_window , 0, max_operator, morphology_operations)</div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#gaf78d2155d30b728fc413803745b67a9b">cv.createTrackbar</a>(title_trackbar_element_type, title_window , 0, max_elem, morphology_operations)</div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#gaf78d2155d30b728fc413803745b67a9b">cv.createTrackbar</a>(title_trackbar_kernel_size, title_window , 0, max_kernel_size, morphology_operations)</div><div class="line"></div><div class="line">morphology_operations(0)</div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7">cv.waitKey</a>()</div></div><!-- fragment -->  </div> <h2>Explanation </h2>
<ol type="1">
<li>Let's check the general structure of the C++ program:<ul>
<li>Load an image</li>
<li>Create a window to display results of the Morphological operations</li>
<li>Create three Trackbars for the user to enter parameters:<ul>
<li>The first trackbar <b>Operator</b> returns the kind of morphology operation to use (<b>morph_operator</b>). <div class="fragment"><div class="line">  <a class="code" href="../../d7/dfc/group__highgui.html#gaf78d2155d30b728fc413803745b67a9b">createTrackbar</a>(<span class="stringliteral">&quot;Operator:\n 0: Opening - 1: Closing  \n 2: Gradient - 3: Top Hat \n 4: Black Hat&quot;</span>, window_name, &amp;morph_operator, max_operator, Morphology_Operations );</div></div><!-- fragment --></li>
<li>The second trackbar <b>Element</b> returns <b>morph_elem</b>, which indicates what kind of structure our kernel is: <div class="fragment"><div class="line">  <a class="code" href="../../d7/dfc/group__highgui.html#gaf78d2155d30b728fc413803745b67a9b">createTrackbar</a>( <span class="stringliteral">&quot;Element:\n 0: Rect - 1: Cross - 2: Ellipse&quot;</span>, window_name,</div><div class="line">                  &amp;morph_elem, max_elem,</div><div class="line">                  Morphology_Operations );</div></div><!-- fragment --></li>
<li>The final trackbar <b>Kernel Size</b> returns the size of the kernel to be used (<b>morph_size</b>) <div class="fragment"><div class="line">  <a class="code" href="../../d7/dfc/group__highgui.html#gaf78d2155d30b728fc413803745b67a9b">createTrackbar</a>( <span class="stringliteral">&quot;Kernel size:\n 2n +1&quot;</span>, window_name,</div><div class="line">                  &amp;morph_size, max_kernel_size,</div><div class="line">                  Morphology_Operations );</div></div><!-- fragment --></li>
</ul>
</li>
<li>Every time we move any slider, the user's function <b>Morphology_Operations</b> will be called to effectuate a new morphology operation and it will update the output image based on the current trackbar values. <div class="fragment"><div class="line"></div><div class="line"><span class="keywordtype">void</span> Morphology_Operations( <span class="keywordtype">int</span>, <span class="keywordtype">void</span>* )</div><div class="line">{</div><div class="line">  <span class="comment">// Since MORPH_X : 2,3,4,5 and 6</span></div><div class="line"><span class="comment"></span>  <span class="keywordtype">int</span> operation = morph_operator + 2;</div><div class="line"></div><div class="line">  Mat element = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gac342a1bb6eabf6f55c803b09268e36dc">getStructuringElement</a>( morph_elem, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>( 2*morph_size + 1, 2*morph_size+1 ), <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>( morph_size, morph_size ) );</div><div class="line"></div><div class="line">  <a class="code" href="../../d4/d86/group__imgproc__filter.html#ga67493776e3ad1a3df63883829375201f">morphologyEx</a>( src, dst, operation, element );</div><div class="line">  <a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">imshow</a>( window_name, dst );</div><div class="line">}</div></div><!-- fragment --> We can observe that the key function to perform the morphology transformations is <a class="el" href="../../d4/d86/group__imgproc__filter.html#ga67493776e3ad1a3df63883829375201f">cv::morphologyEx</a> . In this example we use four arguments (leaving the rest as defaults):<ul>
<li><b>src</b> : Source (input) image</li>
<li><b>dst</b>: Output image</li>
<li><p class="startli"><b>operation</b>: The kind of morphology transformation to be performed. Note that we have 5 alternatives:</p><ul>
<li><em>Opening</em>: MORPH_OPEN : 2</li>
<li><em>Closing</em>: MORPH_CLOSE: 3</li>
<li><em>Gradient</em>: MORPH_GRADIENT: 4</li>
<li><em>Top Hat</em>: MORPH_TOPHAT: 5</li>
<li><em>Black Hat</em>: MORPH_BLACKHAT: 6</li>
</ul>
<p class="startli">As you can see the values range from &lt;2-6&gt;, that is why we add (+2) to the values entered by the Trackbar: </p><div class="fragment"><div class="line">  <span class="keywordtype">int</span> operation = morph_operator + 2;</div></div><!-- fragment --></li>
<li><b>element</b>: The kernel to be used. We use the function <a class="el" href="../../d4/d86/group__imgproc__filter.html#gac342a1bb6eabf6f55c803b09268e36dc">cv::getStructuringElement</a> to define our own structure.</li>
</ul>
</li>
</ul>
</li>
</ol>
<h2>Results </h2>
<ul>
<li><p class="startli">After compiling the code above we can execute it giving an image path as an argument. Results using the image: <b>baboon.png</b>:</p>
<div class="image">
<img src="../../Morphology_2_Tutorial_Original_Image.jpg" alt="Morphology_2_Tutorial_Original_Image.jpg"/>
</div>
</li>
<li><p class="startli">And here are two snapshots of the display window. The first picture shows the output after using the operator <b>Opening</b> with a cross kernel. The second picture (right side, shows the result of using a <b>Blackhat</b> operator with an ellipse kernel.</p>
<div class="image">
<img src="../../Morphology_2_Tutorial_Result.jpg" alt="Morphology_2_Tutorial_Result.jpg"/>
</div>
 </li>
</ul>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:36 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
